package com.christina.engine.context.impl;

import com.christina.engine.context.ContextManager;
import com.christina.engine.context.model.ConversationContext;
import com.christina.engine.context.model.UserContext;
import com.christina.utils.RedisUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;

/**
 * 基于Redis的上下文管理器实现
 * 
 * @author Christina
 */
@Slf4j
@Component
public class RedisContextManager implements ContextManager {

    private final RedisUtil redisUtil;
    private final ObjectMapper objectMapper;
    
    // 缓存过期时间
    private static final long USER_CONTEXT_EXPIRE_SECONDS = 7200; // 2小时
    private static final long CONVERSATION_CONTEXT_EXPIRE_SECONDS = 3600; // 1小时

    public RedisContextManager(RedisUtil redisUtil, ObjectMapper objectMapper) {
        this.redisUtil = redisUtil;
        this.objectMapper = objectMapper;
    }

    @Override
    public UserContext getUserContext(Long userId) {
        try {
            String key = buildUserContextKey(userId);
            String contextJson = redisUtil.getString(key);
            
            if (contextJson != null) {
                UserContext context = objectMapper.readValue(contextJson, UserContext.class);
                log.debug("获取用户上下文成功: userId={}", userId);
                return context;
            }
            
            // 创建新的用户上下文
            UserContext newContext = createDefaultUserContext(userId);
            updateUserContext(userId, newContext);
            
            return newContext;
            
        } catch (Exception e) {
            log.error("获取用户上下文失败: userId={}", userId, e);
            return createDefaultUserContext(userId);
        }
    }

    @Override
    public void updateUserContext(Long userId, UserContext context) {
        try {
            String key = buildUserContextKey(userId);
            context.setUpdateTime(LocalDateTime.now());
            
            String contextJson = objectMapper.writeValueAsString(context);
            redisUtil.setString(key, contextJson, USER_CONTEXT_EXPIRE_SECONDS, TimeUnit.SECONDS);
            
            log.debug("更新用户上下文成功: userId={}", userId);
            
        } catch (Exception e) {
            log.error("更新用户上下文失败: userId={}", userId, e);
        }
    }

    @Override
    public ConversationContext getConversationContext(String sessionId) {
        try {
            String key = buildConversationContextKey(sessionId);
            String contextJson = redisUtil.getString(key);
            
            if (contextJson != null) {
                ConversationContext context = objectMapper.readValue(contextJson, ConversationContext.class);
                
                // 检查是否过期
                if (context.getExpireTime().isAfter(LocalDateTime.now())) {
                    log.debug("获取对话上下文成功: sessionId={}", sessionId);
                    return context;
                } else {
                    log.info("对话上下文已过期: sessionId={}", sessionId);
                    redisUtil.del(key);
                }
            }
            
            // 创建新的对话上下文
            ConversationContext newContext = createDefaultConversationContext(sessionId);
            updateConversationContext(sessionId, newContext);
            
            return newContext;
            
        } catch (Exception e) {
            log.error("获取对话上下文失败: sessionId={}", sessionId, e);
            return createDefaultConversationContext(sessionId);
        }
    }

    @Override
    public void updateConversationContext(String sessionId, ConversationContext context) {
        try {
            String key = buildConversationContextKey(sessionId);
            context.setLastActiveTime(LocalDateTime.now());
            context.setExpireTime(LocalDateTime.now().plusSeconds(CONVERSATION_CONTEXT_EXPIRE_SECONDS));
            
            String contextJson = objectMapper.writeValueAsString(context);
            redisUtil.setString(key, contextJson, CONVERSATION_CONTEXT_EXPIRE_SECONDS, TimeUnit.SECONDS);
            
            log.debug("更新对话上下文成功: sessionId={}", sessionId);
            
        } catch (Exception e) {
            log.error("更新对话上下文失败: sessionId={}", sessionId, e);
        }
    }

    @Override
    public void clearExpiredContexts() {
        log.info("开始清理过期上下文");
        
        try {
            // Redis的TTL机制会自动清理过期的键
            // 这里可以添加额外的清理逻辑，比如清理数据库中的过期记录
            
            log.info("过期上下文清理完成");
            
        } catch (Exception e) {
            log.error("清理过期上下文失败", e);
        }
    }

    @Override
    public Object mergeContexts(UserContext userContext, ConversationContext conversationContext) {
        try {
            MergedContext mergedContext = MergedContext.builder()
                .userId(userContext.getUserId())
                .sessionId(conversationContext.getSessionId())
                .userProfile(userContext.getProfile())
                .userPreferences(userContext.getPreferences())
                .conversationHistory(conversationContext.getConversationHistory())
                .currentTopic(conversationContext.getCurrentTopic())
                .conversationState(conversationContext.getState())
                .sessionVariables(conversationContext.getSessionVariables())
                .build();
            
            log.debug("上下文合并成功: userId={}, sessionId={}", 
                userContext.getUserId(), conversationContext.getSessionId());
            
            return mergedContext;
            
        } catch (Exception e) {
            log.error("上下文合并失败", e);
            return new HashMap<>();
        }
    }

    /**
     * 构建用户上下文缓存键
     */
    private String buildUserContextKey(Long userId) {
        return "context:user:" + userId;
    }

    /**
     * 构建对话上下文缓存键
     */
    private String buildConversationContextKey(String sessionId) {
        return "context:conversation:" + sessionId;
    }

    /**
     * 创建默认用户上下文
     */
    private UserContext createDefaultUserContext(Long userId) {
        return UserContext.builder()
            .userId(userId)
            .profile(UserContext.UserProfile.builder().build())
            .preferences(UserContext.UserPreferences.builder()
                .emailNotification(true)
                .pushNotification(true)
                .communicationStyle("friendly")
                .responseLength("medium")
                .customPreferences(new HashMap<>())
                .build())
            .behaviorHistory(new ArrayList<>())
            .createTime(LocalDateTime.now())
            .updateTime(LocalDateTime.now())
            .build();
    }

    /**
     * 创建默认对话上下文
     */
    private ConversationContext createDefaultConversationContext(String sessionId) {
        return ConversationContext.builder()
            .sessionId(sessionId)
            .conversationHistory(new ArrayList<>())
            .state(ConversationContext.ConversationState.ACTIVE)
            .pendingTasks(new ArrayList<>())
            .sessionVariables(new HashMap<>())
            .startTime(LocalDateTime.now())
            .lastActiveTime(LocalDateTime.now())
            .expireTime(LocalDateTime.now().plusSeconds(CONVERSATION_CONTEXT_EXPIRE_SECONDS))
            .build();
    }

    /**
     * 合并后的上下文模型
     */
    @lombok.Data
    @lombok.Builder
    public static class MergedContext {
        private Long userId;
        private String sessionId;
        private UserContext.UserProfile userProfile;
        private UserContext.UserPreferences userPreferences;
        private java.util.List<ConversationContext.ConversationTurn> conversationHistory;
        private String currentTopic;
        private ConversationContext.ConversationState conversationState;
        private java.util.Map<String, Object> sessionVariables;
    }
}